package com.seeyon.apps.lzmzj.kit;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 日期处理工具类
 *
 * @Copyright Beijing Seeyon Software Co.,LTD
 */
public class DateKit {

    private static SimpleDateFormat simple = new SimpleDateFormat("yyyyMMdd");

    private static SimpleDateFormat sixFormat = new SimpleDateFormat("yyMMdd");

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private static SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd");

    private static SimpleDateFormat monthFormat = new SimpleDateFormat("yyyy-MM");

    private static SimpleDateFormat weekDay = new SimpleDateFormat("MM-dd");

    private static SimpleDateFormat hour = new SimpleDateFormat("HH:mm");

    private static SimpleDateFormat hourMin = new SimpleDateFormat("HHmmss");

    private static SimpleDateFormat detailDate = new SimpleDateFormat("yyyy-MM-dd HH:mm");

    private static SimpleDateFormat detailDateTime = new SimpleDateFormat("yyyyMMddHHmmss");


    private static final String dayNames[] = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};

    /**
     * 获取给定日期的年份
     *
     * @param date 一个Date对象，表示需要获取年份的日期
     * @return 给定日期的年份
     */
    public static int getYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.YEAR);
    }

    /**
     * 获取日期的格式化字符串，格式为："yyyy-MM-dd"
     *
     * @param date 传入的日期对象
     * @return 格式化后的字符串
     */
    public static String getSixDate(Date date) {
        if (null == date) {
            return sixFormat.format(new Date());
        }
        return sixFormat.format(date);
    }


    /**
     * 获取指定日期是当年的第几周
     *
     * @param date 指定日期
     * @return 当年的周数
     */
    public static int getWeekNum(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int week = cal.get(Calendar.WEEK_OF_YEAR);
        // 如果是星期天，那么需要减1
        if ("星期日".equals(DateKit.getDayWeekName(date))) {
            week -= 1;
        }
        return week;
    }


    /**
     * 计算当前日期所在周的起始日期和结束日期
     *
     * @param param 参数映射，用于存储起始日期和结束日期
     */
    public static void getWeekInterval(Map<String, Object> param) {
        Calendar cal = Calendar.getInstance();

        // 判断要计算的日期是否是周日，如果是则减一天计算周六的，否则会出问题，计算到下一周去了
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK); // 获得当前日期是一个星期的第几天
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }

        // 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        cal.setFirstDayOfWeek(Calendar.MONDAY);

        // 获得当前日期是一个星期的第几天
        int day = cal.get(Calendar.DAY_OF_WEEK);

        // 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);

        param.put("startDate", cal.getTime()); // 参数映射中存储起始日期

        cal.add(Calendar.DATE, 6);

        param.put("endDate", cal.getTime()); // 参数映射中存储结束日期
    }


    /**
     * 计算当前日期所在周的起始日期和结束日期
     *
     * @param param 参数映射，用于存储起始日期和结束日期
     * @param now   当前日期
     */
    public static void getWeekInterval(Map<String, Object> param, Date now) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(now);

        // 判断要计算的日期是否是周日，如果是则减一天计算周六的，否则会出问题，计算到下一周去了
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK); // 获得当前日期是一个星期的第几天
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }

        // 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        cal.setFirstDayOfWeek(Calendar.MONDAY);

        // 获得当前日期是一个星期的第几天
        int day = cal.get(Calendar.DAY_OF_WEEK);

        // 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
        String time = DateKit.getDayDate(cal.getTime()) + " 00:00:00";
        try {
            param.put("beginDate", DateKit.getdayDate(time));
        } catch (Exception e) {
        }

        cal.add(Calendar.DATE, 6);
        time = DateKit.getDayDate(cal.getTime()) + " 23:59:59";
        try {
            param.put("endDate", DateKit.getdayDate(time));
        } catch (Exception e) {
        }
    }


    /**
     * 获取简单的日期字符串
     *
     * @param object 对象
     * @return 简单的日期字符串
     * @throws Exception 异常
     */
    public static String getSimpleDate(Object object) throws Exception {
        if (object == null) {
            return "";
        }
        Date date = simple.parse(StrKit.str(object));
        return dayFormat.format(date);
    }


    /**
     * 获取指定日期的简单小时和分钟字符串表示。
     *
     * @param date 指定的日期
     * @return 简单小时和分钟字符串表示，如果日期为null则返回空字符串
     */
    public static String getSimpleHourMin(Date date) {
        if (date == null) {
            return "";
        }
        return hourMin.format(date);
    }


    /**
     * 根据给定的日期对象获取该日期的天数
     *
     * @param date 传入的日期对象
     * @return 返回日期的天数，如果日期对象为空则返回空字符串
     */
    public static String getDate4Cal(Date date) {
        if (date == null) {
            return "";
        }
        return hour.format(date);
    }


    /**
     * 获取指定日期的字符串形式
     *
     * @param date 指定的日期对象
     * @return 返回日期的字符串形式，如果日期对象为空则返回空字符串
     */
    public static String getDateString(Date date) {
        if (date == null) {
            return "";
        }
        return sdf.format(date);
    }


    /**
     * 获取指定日期的天部分的字符串表示。
     *
     * @param date 指定的日期对象
     * @return 返回日期的天部分的字符串表示，如果日期对象为空则返回空字符串
     */
    public static String getDayDate(Date date) {
        if (date == null) {
            return "";
        }
        return dayFormat.format(date);
    }


    public static String getWeekDay(Date date) {
        if (date == null) {
            return "";
        }
        return weekDay.format(date);
    }

    /**
     * 获取指定天数后的日期
     *
     * @param day 天数，正数表示往后计算天数，负数表示往前计算天数
     * @return 计算后的日期
     */
    public static Date getDayAfter(int day) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, day);
        return cal.getTime();
    }


    /**
     * 获取指定日期的后 n 天的日期
     *
     * @param d   指定日期
     * @param day 后推的天数
     * @return 后 n 天的日期
     */
    public static Date getDayAfter(Date d, int day) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(d);
        cal.add(Calendar.DATE, day);
        return cal.getTime();
    }


    /**
     * 根据给定的年份和月份，计算该月的天数
     *
     * @param year  年份
     * @param month 月份，取值范围为0-11
     * @return 该月的天数
     */
    public static int getDaysByYearMonth(int year, int month) {
        Calendar a = Calendar.getInstance();
        a.set(Calendar.YEAR, year);
        a.set(Calendar.MONTH, month);
        a.set(Calendar.DATE, 1);
        a.roll(Calendar.DATE, -1);
        int maxDate = a.get(Calendar.DATE);
        return maxDate;
    }


    /**
     * 获取给定日期是星期几的名称
     *
     * @param date 给定的日期
     * @return 给定日期是星期几的名称
     */
    public static String getDayWeekName(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        if (dayOfWeek < 0)
            dayOfWeek = 0;
        return dayNames[dayOfWeek];
    }


    /**
     * 根据传入的日期字符串获取对应的Date对象
     *
     * @param dateStr 日期字符串
     * @return 对应的Date对象
     * @throws Exception 如果无法解析日期字符串则抛出异常
     */
    public static Date getdayDate(String dateStr) throws Exception {
        try {
            // 使用sdf格式化日期字符串并返回对应的Date对象
            return sdf.parse(dateStr);
        } catch (Exception e) {
            try {
                // 使用detailDate格式化日期字符串并返回对应的Date对象
                return detailDate.parse(dateStr);
            } catch (Exception e1) {
                try {
                    // 使用dayFormat格式化日期字符串并返回对应的Date对象
                    return dayFormat.parse(dateStr);
                } catch (Exception e2) {
                    try {
                        // 使用simple格式化日期字符串并返回对应的Date对象
                        return simple.parse(dateStr);
                    } catch (Exception e3) {
                        // 使用monthFormat格式化日期字符串并返回对应的Date对象
                        return monthFormat.parse(dateStr);
                    }
                }
            }
        }
    }


    /**
     * 获取指定日期所在周的周数和日期，并以字符串形式返回
     *
     * @param now 指定日期
     * @return 返回格式为"第X周:开始日期至结束日期"
     */
    public static String getWeekNumAndDateZone(Date now) {
        StringBuffer sb = new StringBuffer();
        sb.append("第");
        sb.append(getWeekNum(now));
        sb.append("周:");
        Map<String, Object> param = new HashMap<String, Object>();
        getWeekInterval(param, now);
        Date beginDate = (Date) param.get("beginDate");
        Date endDate = (Date) param.get("endDate");
        sb.append(dayFormat.format(beginDate));
        sb.append("至");
        sb.append(dayFormat.format(endDate));
        return sb.toString();
    }


    /**
     * 从给定的日期和时间创建一个日期对象
     *
     * @param d    日期对象
     * @param time 时间字符串
     * @return 新的日期对象
     * @throws ParseException 解析异常
     */
    public static Date getDateFromTime(Date d, String time) throws ParseException {
        String dateTime = dayFormat.format(d) + " " + time;
        return detailDate.parse(dateTime);
    }


    /**
     * 获取当前日期和时间的字符串表示
     *
     * @return 返回当前日期和时间的字符串表示
     * @throws ParseException 解析异常
     */
    public static String getDateTime() throws ParseException {
        String dateTime = detailDateTime.format(new Date());
        return dateTime;
    }

}
